﻿Imports System.Runtime.InteropServices

Public Class StopPC
    Private WithEvents timerStop As New Timer
    Private _Interval As Double = 3600000
    Private _shutdownmode As ShutdownModeType = ShutdownModeType.Arreter
    Private debutlancement As DateTime = DateTime.Now
    Private _actif As Boolean = False
    Public Event InfoStop()
    Public Event InfoClose()


    Public Sub Lancer()
        timerStop.Enabled = True
        timerStop.Interval = CInt(_Interval)
        timerStop.Start()
        debutlancement = DateTime.Now
        _actif = True
    End Sub

    Public Sub Arreter()
        timerStop.Enabled = False
        timerStop.Stop()
        _actif = False
    End Sub
    Public ReadOnly Property Actif As Boolean
        Get
            Return _actif
        End Get
    End Property
    Public ReadOnly Property TempsRestant As Double
        Get
            Return Math.Max(debutlancement.AddMilliseconds(_Interval).Subtract(DateTime.Now).TotalMinutes, 0D)
        End Get
    End Property

    Public Property Interval As Double
        Get
            Return _Interval / 60000
        End Get
        Set(ByVal value As Double)
            _Interval = value * 60000
            timerStop.Interval = CInt(value)
        End Set
    End Property


    Public Property ShutdownMode As ShutdownModeType
        Get
            Return _shutdownmode
        End Get
        Set(ByVal value As ShutdownModeType)
            _shutdownmode = value
        End Set
    End Property
    Public Enum ShutdownModeType
        Fermer
        Supendre
        Hiberner
        Arreter
    End Enum
    Private Sub timerStop_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles timerStop.Tick
        RaiseEvent InfoStop()
        Select Case _shutdownmode
            Case ShutdownModeType.Fermer
                RaiseEvent InfoClose()
            Case ShutdownModeType.Supendre
                RaiseEvent InfoStop()
                Suspend()
            Case ShutdownModeType.Hiberner
                RaiseEvent InfoStop()
                Hibernate()
            Case ShutdownModeType.Arreter
                RaiseEvent InfoStop()
                Shutdown()
        End Select
    End Sub



    <DllImport("user32.dll")> _
    Shared Function ExitWindowsEx(ByVal operationFlag As Integer, ByVal operationReason As Integer) As Integer
    End Function
    Private Sub Hibernate()
        Application.SetSuspendState(PowerState.Hibernate, True, True)
    End Sub
    Private Sub Suspend()
        Application.SetSuspendState(PowerState.Suspend, True, True)
    End Sub
    Private Sub Shutdown()
        'Process.Start("shutdown", "-s -t 00")
        AcquireShutdownPrivilege()
        ExitWindowsEx(1, 0)
    End Sub


    'this routine enables the Shutdown privilege for the current process, 
    'which is necessary if you want to call ExitWindowsEx.

    Const ANYSIZE_ARRAY As Integer = 1
    Const TOKEN_QUERY As Integer = &H8
    Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20
    Const SE_SHUTDOWN_NAME As String = "SeShutdownPrivilege"
    Const SE_PRIVILEGE_ENABLED As Integer = &H2

    <StructLayout(LayoutKind.Sequential)> _
    Structure LUID
        Public LowPart As UInt32
        Public HighPart As UInt32
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Structure LUID_AND_ATTRIBUTES
        Public Luid2 As LUID
        Public Attributes As UInt32
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Structure TOKEN_PRIVILEGES
        Public PrivilegeCount As UInt32
         _
        Public Privileges() As LUID_AND_ATTRIBUTES
    End Structure

    <DllImport("Advapi32.dll", SetLastError:=True)> _
    Shared Function LookupPrivilegeValue( _
     ByVal lpSystemName As String, _
     ByVal lpName As String, _
     ByRef lpLuid As LUID _
      ) As Boolean
    End Function

    <DllImport("Advapi32.dll", SetLastError:=True)> _
    Shared Function OpenProcessToken( _
     ByVal ProcessHandle As IntPtr, _
     ByVal DesiredAccess As Integer, _
     ByRef TokenHandle As IntPtr _
      ) As Boolean
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)> _
    Shared Function CloseHandle(ByVal hHandle As IntPtr) As Boolean
    End Function

    <DllImport("Advapi32.dll", SetLastError:=True)> _
    Shared Function AdjustTokenPrivileges( _
       ByVal TokenHandle As IntPtr, _
       ByVal DisableAllPrivileges As Boolean, _
       ByRef NewState As TOKEN_PRIVILEGES, _
       ByVal BufferLength As Integer, _
       ByRef PreviousState As TOKEN_PRIVILEGES, _
       ByRef ReturnLength As IntPtr _
     ) As Boolean
    End Function

    Private Sub AcquireShutdownPrivilege()

        Dim lastWin32Error As Integer = 0

        'Get the LUID that corresponds to the Shutdown privilege, if it exists.
        Dim luid_Shutdown As LUID
        If Not LookupPrivilegeValue(Nothing, SE_SHUTDOWN_NAME, luid_Shutdown) Then
            lastWin32Error = Marshal.GetLastWin32Error()
            Throw New System.ComponentModel.Win32Exception(lastWin32Error, _
             "LookupPrivilegeValue failed with error " & lastWin32Error.ToString & ".")
        End If

        'Get the current process's token.
        Dim hProc As IntPtr = Process.GetCurrentProcess().Handle
        Dim hToken As IntPtr
        If Not OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken) Then
            lastWin32Error = Marshal.GetLastWin32Error()
            Throw New System.ComponentModel.Win32Exception(lastWin32Error, _
             "OpenProcessToken failed with error " & lastWin32Error.ToString & ".")
        End If

        Try

            'Set up a LUID_AND_ATTRIBUTES structure containing the Shutdown privilege, marked as enabled.
            Dim luaAttr As New LUID_AND_ATTRIBUTES
            luaAttr.Luid2 = luid_Shutdown
            luaAttr.Attributes = SE_PRIVILEGE_ENABLED

            'Set up a TOKEN_PRIVILEGES structure containing only the shutdown privilege.
            Dim newState As New TOKEN_PRIVILEGES
            newState.PrivilegeCount = 1
            newState.Privileges = New LUID_AND_ATTRIBUTES() {luaAttr}

            'Set up a TOKEN_PRIVILEGES structure for the returned (modified) privileges.
            Dim prevState As TOKEN_PRIVILEGES = New TOKEN_PRIVILEGES
            ReDim prevState.Privileges(CInt(newState.PrivilegeCount))

            'Apply the TOKEN_PRIVILEGES structure to the current process's token.
            Dim returnLength As IntPtr
            If Not AdjustTokenPrivileges(hToken, False, newState, Marshal.SizeOf(prevState), prevState, returnLength) Then
                lastWin32Error = Marshal.GetLastWin32Error()
                Throw New System.ComponentModel.Win32Exception(lastWin32Error, _
                 "AdjustTokenPrivileges failed with error " & lastWin32Error.ToString & ".")
            End If

        Finally
            CloseHandle(hToken)
        End Try






    End Sub
End Class
